package cn.yr.search.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.yr.common.core.domain.vo.PageVo;
import cn.yr.search.bean.ArticleDocBean;
import cn.yr.search.repository.ArticleElasticRepository;
import cn.yr.search.service.ArticleElasticService;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service("articleElasticService")
public class ArticleElasticServiceImpl implements ArticleElasticService {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;

    @Autowired
    private ArticleElasticRepository articleElasticRepository;

    @Override
    public Boolean createIndex() {
        return elasticsearchTemplate.indexOps(ArticleDocBean.class).create();
    }

    @Override
    public Boolean deleteIndex() {
        return elasticsearchTemplate.indexOps(ArticleDocBean.class).delete();
    }

    @Override
    public void save(ArticleDocBean articleDocBean) {

        articleElasticRepository.save(articleDocBean);
    }

    @Override
    public void saveAll(List<ArticleDocBean> list) {
        articleElasticRepository.saveAll(list);
    }

    @Override
    public void delete(Long id) {
        articleElasticRepository.deleteById(id);
    }

    @Override
    public void update(ArticleDocBean articleDocBean) {
        articleElasticRepository.save(articleDocBean);
    }

    @Override
    public Iterator<ArticleDocBean> findAll() {
        return articleElasticRepository.findAll().iterator();
    }

    @Override
    public PageVo<ArticleDocBean> findByTitle(PageVo<ArticleDocBean> pageVo) {
        Pageable pageable = PageRequest.of((int) pageVo.getCurrent(), (int) pageVo.getSize());
        Page<ArticleDocBean> page = articleElasticRepository.findByTitle(pageVo.getAs("kw"), pageable);
        pageVo.setRecords(page.getContent());
        pageVo.setTotal(page.getTotalElements());
        return pageVo;
    }

    @Override
    public PageVo<ArticleDocBean> find(PageVo<ArticleDocBean> pageVo) {
        Pageable pageable = PageRequest.of((int) pageVo.getCurrent(), (int) pageVo.getSize());
        Page<ArticleDocBean> page = articleElasticRepository.find(pageVo.getAs("kw"), pageable);
        pageVo.setRecords(page.getContent());
        pageVo.setTotal(page.getTotalElements());
        return pageVo;
    }

    @Override
    public Page<ArticleDocBean> findByFirstCode(String firstCode) {
        return null;
    }

    @Override
    public Page<ArticleDocBean> findBySecordCode(String secordCode) {
        return null;
    }

    @Override
    public PageVo<ArticleDocBean> pageSearch(PageVo<ArticleDocBean> pageVo) {
        String preTag = "<font color='#f36440'>";
        String postTag = "</font>";
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
            //查询条件
            .withQuery(
                    QueryBuilders.boolQuery().must(
                            QueryBuilders.multiMatchQuery(pageVo.getAs("kw"), "title", "description", "author")
                    ).must(
                            QueryBuilders.matchQuery("type", pageVo.getAs("type"))
                    )
            )
            //分页
            .withPageable(PageRequest.of((int) pageVo.getCurrent()-1, (int) pageVo.getSize()))
            //排序
            .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
            //高亮字段显示
            .withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag),
                    new HighlightBuilder.Field("description").preTags(preTag).postTags(postTag),
                    new HighlightBuilder.Field("author").preTags(preTag).postTags(postTag))
            .build();
        SearchHits<ArticleDocBean> searchHits = elasticsearchTemplate.search(nativeSearchQuery, ArticleDocBean.class, IndexCoordinates.of("article"));
        pageVo.setTotal(searchHits.getTotalHits());
        List<ArticleDocBean> articleDocBeans = searchHits.stream().map(searchHit -> {
            ArticleDocBean content = searchHit.getContent();
            List<String> title = searchHit.getHighlightField("title");
            if (CollUtil.isNotEmpty(title)) {
                content.setTitle(title.get(0));
            }
            List<String> author = searchHit.getHighlightField("author");
            if (CollUtil.isNotEmpty(author)) {
                content.setAuthor(author.get(0));
            }
            List<String> description = searchHit.getHighlightField("description");
            if (CollUtil.isNotEmpty(description)) {
                content.setDescription(description.get(0));
            }
            return content;
        }).collect(Collectors.toList());
        pageVo.setRecords(articleDocBeans);
        return pageVo;
    }

}
